import random
#random.seed(2)


def fuzzy_equals(v1, v2, eps=1.0e-4):
	if type(v1) == list or type(v1) == tuple:
		if type(v2) != list and type(v2) != tuple:
			raise RuntimeError("Either both must be sequences or neither")
		if len(v1) != len(v2):
			raise RuntimeError("Sequence lengths must agree")
		for i,v in enumerate(v1):
			if not fuzzy_equals(v, v2[i]):
				return False
		return True
	if type(v2) == list or type(v2) == tuple:
		raise RuntimeError("Either both must be sequences or neither")
	return abs(v1-v2) <= eps

def is_numeric(v):
	return isinstance(v, int) or isinstance(v, float)
	
def is_numeric_seq(v):
	if not (isinstance(v, tuple) or isinstance(v, list)):
		return False
	for x in v:
		if not is_numeric(x):
			return False
	return True

def is_discrete(v):
	"""Returns true if v is a discrete variable -- either None, int, bool,
	string, or a sequence of discrete primitives"""
	if v == None: return True
	if isinstance(v,(str,int,bool)): return True
	elif isinstance(v,(list,tuple)):
		return all(is_discrete(vi) for vi in v)
	return False
	
# drction is <0 for left-hand number, >=0 for right-hand number
def find_value_edge(s, loc, drction):
	addNum = 1
	if drction < 0:
		addNum = -1
	
	edge = loc + addNum
	while True:
		if edge == 0 or edge == len(s)-1:
			break
		if s[edge] == ',':
			edge -= addNum
			break
		if s[edge] == ':':
			raise ParseError("STRIPS: Illegal multi-range range:\n\t" + s)
		edge += addNum
	return edge
	
	

# flattens singletons and sequences into a list
def flatten(value):
	if isinstance(value, (list,tuple)):
		return sum([flatten(vi) for vi in value],[])
	else:
		return [value]
